#pragma once

#include "DataPacketReader.h"
class CDataPacket : public CDataPacketReader
{
public:
	CDataPacket() {}
	CDataPacket(void* lpBuffer, size_t nSize) : CDataPacketReader(lpBuffer, nSize)
	{
		m_pDataEnd = m_pMemory;
	}
public:
	inline void writeBuf(void* lpBuffer, size_t nSize)
	{
		size_t memSize = m_pMemoryEnd - m_pOffset;
		if (memSize < nSize)
		{
			setSize(m_pMemoryEnd - m_pMemory + nSize);
		}
		memcpy(m_pOffset, lpBuffer, nSize);
		m_pOffset += nSize;

		if (m_pOffset > m_pDataEnd)
			m_pDataEnd = m_pOffset;
	}

	template <typename T>
	void writeAtom(T data)
	{
		writeBuf(&data, sizeof(T));
	}

	void writeString(const char* str)
	{
		unsigned short len = str?strlen(str):0;
		writeAtom(len);
		writeBuf((void*)str, len);
	}

	void writeWString(const wchar_t* str)
	{
		unsigned short len = str?wcslen(str):0;
		writeAtom(len);
		writeBuf((void*)str, len*sizeof(*str));
	}

	void setSize(size_t newSize)
	{
		char* pOldMemory = m_pMemory;
		newSize = (newSize + MemoryAlignmentSize) & (~(MemoryAlignmentSize-1));
		char* pMemory = (char*)malloc(newSize);

		size_t length = m_pDataEnd - m_pMemory;
		size_t offset = m_pOffset - m_pMemory;
		memcpy(pMemory, m_pMemory, length);

		m_pMemory = pMemory;
		m_pMemoryEnd = m_pMemory + newSize;
		m_pOffset = m_pMemory + offset;
		m_pDataEnd = m_pMemory + length;

		if (pOldMemory)
			free(pMemory);		
	}
private:
	static const size_t MemoryAlignmentSize = 256;
};